// excerpts from http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include "Acceptor.h"

#include "EventLoop.h"
#include "InetAddress.h"
#include "SocketsOps.h"

#include <boost/bind.hpp>

using namespace learnmuduo;

Acceptor::Acceptor(EventLoop* loop, const InetAddress& listenAddr)
  : loop_(loop),
    acceptSocket_(sockets::createNonblockingOrDie()),
    acceptChannel_(loop, acceptSocket_.fd()),
    listenning_(false)
{
  acceptSocket_.setReuseAddr(true); // // 启用地址复用，避免 TIME_WAIT 时绑定失败
  acceptSocket_.bindAddress(listenAddr); // 绑定监听地址
  acceptChannel_.setReadCallback(
      boost::bind(&Acceptor::handleRead, this)); // 设置监听 Channel 的读事件回调
}

void Acceptor::listen()
{
  loop_->assertInLoopThread();
  listenning_ = true;
  acceptSocket_.listen(); // 开始监听
  acceptChannel_.enableReading(); // 让 Poller 关注“可读”，即新的连接到达
}

void Acceptor::handleRead()
{
  loop_->assertInLoopThread();
  InetAddress peerAddr(0);
  //FIXME loop until no more; 如果一次触发有多个连接，当前只 accept 一次，可改为循环
  int connfd = acceptSocket_.accept(&peerAddr);
  if (connfd >= 0) {
    if (newConnectionCallback_) {
      newConnectionCallback_(connfd, peerAddr); // 将新连接交给上层（通常是 TcpServer）
    } else {
      sockets::close(connfd); // 如果没有设置回调，直接关闭避免 fd 泄漏
    }
  }
}
